package org.vaadin.nf4v.core.config.builder;

import com.vaadin.ui.Component;
import org.vaadin.nf4v.core.config.ContextConfig;
import org.vaadin.nf4v.core.config.ContextConfigurationException;
import org.vaadin.nf4v.core.config.PageConfig;
import org.vaadin.nf4v.core.config.process.NavigationConfigProcessor;
import org.vaadin.nf4v.core.handler.Handler;

import java.util.LinkedList;
import java.util.List;

/**
 * Page configuration builder (DSL).
 */
public class ContextPagesConfigBuilder {
    private List<ContextConfig> contexts;
    private PageConfig currentPage;
    private NavigationConfigProcessor navigationConfigProcessor;

    private boolean homePageSet = false;
    private List<String> uris = new LinkedList<String>();

    ContextPagesConfigBuilder(List<ContextConfig> contexts, NavigationConfigProcessor navigationConfigProcessor) {
        this.contexts = contexts;
        this.navigationConfigProcessor = navigationConfigProcessor;
    }

    /**
     * Sets page class.
     *
     * @param pageClass page class
     * @return context pages builder instance
     */
    public ContextPagesConfigBuilder page(Class<? extends Component> pageClass) {
        if (pageClass == null) {
            throw new ContextConfigurationException("Page class can't be null");
        }
        PageConfig pageConfig = new PageConfig();
        pageConfig.setPageClass(pageClass);
        //remembering last created page config to apply specific page settings to it.
        currentPage = pageConfig;

        for (ContextConfig cont : contexts) {
            cont.addPage(pageConfig);
        }
        return this;
    }

    /**
     * Sets page uri.
     * Uri should be unique within context.
     *
     * @param uri page uri
     * @return context pages builder instance
     */
    public ContextPagesConfigBuilder uri(String uri) {
        if (currentPage == null) {
            throw new ContextConfigurationException("Page not defined: use page(class) to define page first");
        }
        if (uri == null || "".equals(uri.trim())) {
            // actually uri can be empty, but shouldn't be explicitly set to null
            throw new ContextConfigurationException("Uri can't be empty");
        }
        uri = uri.trim();
        if (uris.contains(uri)){
            throw new ContextConfigurationException("Duplicate uri");
        }
        uris.add(uri);
        currentPage.setUri(uri);
        return this;
    }

    /**
     * Marks current page as home page
     *
     * @return context pages builder instance
     */
    public ContextPagesConfigBuilder asHomePage() {
        if (currentPage == null) {
            throw new ContextConfigurationException("Page not defined: use page(class) to define page first");
        }
        if (homePageSet){
            throw new ContextConfigurationException("Home page is already registered");
        }
        homePageSet = true;
        currentPage.setHomePage(true);
        return this;
    }

    /**
     * ALlows to register page configuration parameter.
     *
     * @param name  parameter name
     * @param value parameter value
     * @return context pages builder instance
     */
    public ContextPagesConfigBuilder param(String name, String value) {
        if (currentPage == null) {
            throw new ContextConfigurationException("Page not defined: use page(class) to define page first");
        }
        currentPage.setParam(name, value);
        return this;
    }
}
